using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum WindowAnimType
{
    Alpha,
    Scale,
    Rotation,
    Translate,
}

public class IUIAnimElem
{
    public float duration;
}

public class UIAnimElem : IUIAnimElem
{
    public WindowAnimType type = WindowAnimType.Alpha;
    public UITweener.Method method;
    public float from;
    public float to;
    public Vector2 vFrom;
    public Vector2 vTo;
}

public class UIAnimGroup : IUIAnimElem
{
    public List<UIAnimElem> anims = new List<UIAnimElem>();
}

public class RootWindowManager: Singleton<RootWindowManager>
{
	private static int windowDepthCount = 100;
	public readonly static int alertDialogLayer0 = 2000 / windowDepthCount;
	public readonly static int alertDialogLayer9 = 2900 / windowDepthCount;

    public static IUIAnimElem globalAnim = null;
    public static bool globalAnimForward = true;

    public const float tweenDuration = 0.4f;

        public static UIAnimGroup FadeIn = new UIAnimGroup()
        {
            duration = tweenDuration,
            anims = new List<UIAnimElem>()
                {
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Alpha,
                        method = UITweener.Method.EaseOut,
                        from = 0,
                        to = 1
                    },
                }
        };

        public static UIAnimGroup ScaleFadeIn = new UIAnimGroup()
        {
            duration = tweenDuration,
            anims = new List<UIAnimElem>()
                {
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Alpha,
                        method = UITweener.Method.EaseOut,
                        from = 0,
                        to = 1
                    },
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Scale,
                        method = UITweener.Method.EaseOut,
                        from = 2f,
                        to = 1
                    },
                }
        };

    public static UIAnimGroup RotateScaleFadeIn = new UIAnimGroup()
        {
            duration = tweenDuration,
            anims = new List<UIAnimElem>()
                {
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Alpha,
                        method = UITweener.Method.EaseOut,
                        from = 0,
                        to = 1
                    },
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Scale,
                        method = UITweener.Method.EaseOut,
                        from = 2f,
                        to = 1
                    },
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Rotation,
                        method = UITweener.Method.EaseOut,
                        from = 30,
                        to = 0
                    }
                }
        };

    public static UIAnimGroup FadeOut = new UIAnimGroup()
        {
            duration = tweenDuration,
            anims = new List<UIAnimElem>()
                {
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Alpha,
                        method = UITweener.Method.EaseIn,
                        from = 1,
                        to = 0
                    },
                }
        };

    public static UIAnimGroup ScaleFadeOut = new UIAnimGroup()
        {
            duration = tweenDuration,
            anims = new List<UIAnimElem>()
                {
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Alpha,
                        method = UITweener.Method.EaseIn,
                        from = 1,
                        to = 0
                    },
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Scale,
                        method = UITweener.Method.EaseIn,
                        from = 1,
                        to = 0.5f
                    },
                }
        };

    public static UIAnimGroup RotateScaleFadeOut = new UIAnimGroup()
        {
            duration = tweenDuration,
            anims = new List<UIAnimElem>()
                {
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Alpha,
                        method = UITweener.Method.EaseIn,
                        from = 1,
                        to = 0
                    },
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Scale,
                        method = UITweener.Method.EaseIn,
                        from = 1,
                        to = 0.5f
                    },
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Rotation,
                        method = UITweener.Method.EaseIn,
                        from = 0,
                        to = 30
                    }
                }
        };

    public static UIAnimGroup TranslateFadeIn = new UIAnimGroup()
        {
            duration = tweenDuration,
            anims = new List<UIAnimElem>()
                {
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Alpha,
                        method = UITweener.Method.EaseOut,
                        from = 0,
                        to = 1
                    },
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Translate,
                        method = UITweener.Method.Linear,
                        vFrom = new Vector2(0.3f, 0.3f),
                        vTo = Vector2.zero
                    },
                }
        };

    public static UIAnimGroup TranslateFadeOut = new UIAnimGroup()
        {
            duration = tweenDuration,
            anims = new List<UIAnimElem>()
                {
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Alpha,
                        method = UITweener.Method.EaseIn,
                        from = 1,
                        to = 0
                    },
                    new UIAnimElem()
                    {
                        type = WindowAnimType.Translate,
                        method = UITweener.Method.Linear,
                        vFrom = Vector2.zero,
                        vTo = new Vector2(-0.3f, -0.3f)
                    },
                }
        };

    Dictionary<int, WindowManager> winManagerMap = new Dictionary<int, WindowManager>();
    GameObject _uiRoot;
    public GameObject uiRoot
    {
        get
        {
			if (_uiRoot == null)
			{
                for(int i = 0; i < UIRoot.list.Count; i++)
                {
                    UIRootEx tempRoot = UIRoot.list[i] as UIRootEx;
                    if (tempRoot != null && tempRoot.isMainRoot)
                    {
                        _uiRoot = tempRoot.gameObject;
                        GameObject.DontDestroyOnLoad(_uiRoot);
                        break;
                    }
                }

                if(_uiRoot == null)
                {
                    _uiRoot = GameObject.FindObjectOfType<Canvas>().gameObject;
                }
			}
            return _uiRoot;
        }
    }

    public RootWindowManager()
    {
        
//        winManager.winParent = uiRoot;
//		winManager.windowDepthCount = 10;
    }

//    public bool isWindowShowing(System.Type t)
//    {
//        return isWindowShowing(t.Name);
//    }
//
//    public bool isWindowShowing(string winName)
//    {
//        Dictionary<int, WindowManager>.Enumerator e = winManagerMap.GetEnumerator();
//        while (e.MoveNext())
//        {
//            if (e.Current.Value.GetWindow(winName) != null)
//            {
//                return true;
//            }
//        }
//        return false;
//    }

    public WindowProxy GetWindow<T>()
    {
        return GetWindow(typeof(T));
    }

    public WindowProxy GetWindow<T>(bool isLast)
    {
        return GetWindow(typeof(T), isLast);
    }

    public WindowProxy GetWindow<T>(int layer, bool isLast)
    {
        return GetWindow(typeof(T), layer, isLast);
    }

    public WindowProxy GetWindow(System.Type t)
    {
        return GetWindow(t.Name, true);
    }

    public WindowProxy GetWindow(System.Type t, bool isLast)
    {
        return GetWindow(t.Name, isLast);
    }

    public WindowProxy GetWindow(System.Type t, int layer, bool isLast)
    {   
        return GetWindow(t.Name, layer, isLast);
    }

    public WindowProxy GetWindow(string winName)
    {
        return GetWindow(winName, true);
    }

    public WindowProxy GetWindow(string winName, bool isLast)
    {
        return GetWindow(winName, -1, isLast);
    }

    public WindowProxy GetWindow(string winName, int layer, bool isLast)
    {   
        if (layer >= 0)
        {
            WindowManager winManager = null;
            if (winManagerMap.TryGetValue(layer, out winManager))
            {
                return winManager.GetWindow(winName, isLast);
            }
        }
        else
        {
            Dictionary<int, WindowManager>.Enumerator e = winManagerMap.GetEnumerator();
            while (e.MoveNext())
            {
                WindowProxy proxy = e.Current.Value.GetWindow(winName);
                if(proxy != null)
                {
                    return proxy;
                }
            }
        }
        return null;
    }

	public WindowProxy GetCurWindow()
	{
		return GetCurWindow(0);
	}

    public WindowProxy GetCurWindow(int layer)
    {
        WindowManager winManager = null;
        if (winManagerMap.TryGetValue(layer, out winManager))
        {
            return winManager.GetCurWindow();
        }
        return null;
    }

	public WindowProxy GetCurTopShowWindow()
	{
		return GetCurTopShowWindow(0);
	}

    public WindowProxy GetCurTopShowWindow(int layer)
    {
        WindowManager winManager = null;
        if (winManagerMap.TryGetValue(layer, out winManager))
        {
            return winManager.GetCurTopShowWindow();
        }
        return null;
    }

    public WindowProxy ShowWindow(System.Type t)
	{
        return ShowWindow(t.Name, 0, true, false);
	}

    public WindowProxy ShowWindow(System.Type t, int layer)
    {
        return ShowWindow(t.Name, layer, true, false);
    }

    public WindowProxy ShowWindow(System.Type t, bool hideCurWindow)
    {
        return ShowWindow(t.Name, 0, hideCurWindow, false);
    }

	public WindowProxy ShowWindow(System.Type t, int layer, bool hideCurWindow)
	{
        return ShowWindow(t.Name, layer, hideCurWindow, false);
	}

	public WindowProxy ShowWindow(System.Type t, bool hideCurWindow, bool isDestroy)
	{
        return ShowWindow(t.Name, 0, hideCurWindow, isDestroy);
	}
		
    public WindowProxy ShowWindow(string windowName, int layer, bool hideCurWindow, bool isDestroy)
    {
        WindowManager winManager = null;
        if (!winManagerMap.TryGetValue(layer, out winManager))
        {
            winManager = new WindowManager();
			winManager.winParent = uiRoot;

			winManager.startDepth = layer * windowDepthCount;
			winManager.windowDepthCount = windowDepthCount;
            winManagerMap.Add(layer, winManager);
        }

        return winManager.ShowWindow(windowName, hideCurWindow, isDestroy);
    }

	public WindowProxy ShowWindow(string windowName)
	{
		return ShowWindow (windowName, 0, true, false);
	}

	public WindowProxy ShowWindow(string windowName, bool hideCurWindow)
	{
		return ShowWindow (windowName, 0, hideCurWindow, false);
	}

	public WindowProxy ShowWindow(string windowName, bool hideCurWindow, bool isDestory)
	{
        return ShowWindow(windowName, 0, hideCurWindow, isDestory);
	}

    public WindowProxy ShowWindow(string windowName, int layer, bool hideCurWindow)
    {
        return ShowWindow(windowName, layer, hideCurWindow, false);
    }

    public WindowProxy ShowWindow<T>(bool hideCurWindow = true, bool isDestory = false)
    {
        return ShowWindow(typeof(T), hideCurWindow, isDestory);
    }

    public void HideAllWindowRemainOne()
    {
        HideAllWindowRemainOne(0, true);
    }

    public void HideAllWindowRemainOne(bool isDestroy)
    {
        HideAllWindowRemainOne(0, isDestroy);
    }

    public void HideAllWindowRemainOne(int layer, bool isDestroy)
    {
        WindowManager winManager = null;
        if (winManagerMap.TryGetValue(layer, out winManager))
        {
            winManager.HideAllWindowRemainOne(isDestroy);
        }
    }

    public void HideAllWindow()
    {
        HideAllWindow(-1, true, 0);
    }

    public void HideAllWindow(bool isDestroy)
    {
        HideAllWindow(-1, isDestroy, 0);
    }

    public void HideAllWindow(bool isDestroy, int remainNum)
    {
        HideAllWindow(-1, isDestroy, remainNum);
    }

    public void HideAllWindow(int layer, bool isDestroy, int remainNum)
    {
        if (layer < 0)
        {
            Dictionary<int, WindowManager>.Enumerator e = winManagerMap.GetEnumerator();
            while (e.MoveNext())
            {
                e.Current.Value.HideAllWindow(isDestroy, remainNum);
            }
        }
        else
        {
            WindowManager winManager = null;
            if (winManagerMap.TryGetValue(layer, out winManager))
            {
                winManager.HideAllWindow(isDestroy, remainNum);
            }
        }
    }

    public void PlayAnimAndHideCurWindow(IUIAnimElem curWindowAnim, bool curForward, IUIAnimElem preWindowAnim, bool preForward, bool isDestory = true)
    {
        PlayAnimAndHideCurWindow(0, curWindowAnim, curForward, preWindowAnim, preForward, isDestory);
    }

    public void PlayAnimAndHideCurWindow(int layer, IUIAnimElem curWindowAnim, bool curForward, IUIAnimElem preWindowAnim, bool preForward, bool isDestory = true)
    {
        WindowManager winManager = null;
        if (winManagerMap.TryGetValue(layer, out winManager))
        {
            winManager.PlayAnimAndHideCurWindow(curWindowAnim, curForward, preWindowAnim, preForward, isDestory);
        }
    }

    public void PlayAnimAndHidePreWindow(IUIAnimElem curWindowAnim, bool curForward, IUIAnimElem preWindowAnim, bool preForward, int action = WindowManager.WinAnimActionHide)
    {
        PlayAnimAndHidePreWindow(0, curWindowAnim, curForward, preWindowAnim, preForward, action);
    }

    public void PlayAnimAndHidePreWindow(int layer, IUIAnimElem curWindowAnim, bool curForward, IUIAnimElem preWindowAnim, bool preForward, int action = WindowManager.WinAnimActionHide)
    {
        WindowManager winManager = null;
        if (winManagerMap.TryGetValue(layer, out winManager))
        {
            winManager.PlayAnimAndHidePreWindow(curWindowAnim, curForward, preWindowAnim, preForward, action);
        }
    }

    public void PlayAnim(IUIAnimElem curWindowAnim, bool curForward, System.Action curCallBack, IUIAnimElem preWindowAnim, bool preForward, System.Action preCallBack)
    {
        PlayAnim(0, curWindowAnim, curForward, curCallBack, preWindowAnim, preForward, preCallBack);
    }

    public void PlayAnim(int layer, IUIAnimElem curWindowAnim, bool curForward, System.Action curCallBack, IUIAnimElem preWindowAnim, bool preForward, System.Action preCallBack)
    {
        WindowManager winManager = null;
        if (winManagerMap.TryGetValue(layer, out winManager))
        {
            PlayAnim(curWindowAnim, curForward, curCallBack, preWindowAnim, preForward, preCallBack);
        }
    }

    public void HideCurWindow()
    {
        HideCurWindow(0, true);
    }

    public void HideCurWindow(bool isDestroy)
    {
        HideCurWindow(0, isDestroy);
    }

    public void HideCurWindow(int layer, bool isDestroy)
    {
        WindowManager winManager = null;
        if (winManagerMap.TryGetValue(layer, out winManager))
        {
            winManager.HideCurWindow(isDestroy);
        }
    }

    public void HidePreWindow()
    {
        HidePreWindow(0, true);
    }

    public void HidePreWindow(bool isDestroy)
    {
        HidePreWindow(0, isDestroy);
    }

    public void HidePreWindow(int layer, bool isDestroy)
    {
        WindowManager winManager = null;
        if (winManagerMap.TryGetValue(layer, out winManager))
        {
            winManager.HidePreWindow(isDestroy);
        }
    }

	public void HideWindow(System.Type t)
	{
		HideWindow(t, true, true);
	}

    public void HideWindow(System.Type t, bool isDestroy, bool isLast)
    {
        HideWindow(t.Name, 0, isDestroy, isLast);
    }

    public void HideWindow(string winName)
    {
        HideWindow(winName, true, true);
    }

    public void HideWindow(string winName, bool isDestroy, bool isLast)
    {
        HideWindow(winName, 0, isDestroy, isLast);
    }

    private void HideWindow(string winName, int layer, bool isDestroy = true, bool isLast = true)
    {
        WindowManager winManager = null;
        if (winManagerMap.TryGetValue(layer, out winManager))
        {
            winManager.HideWindow(winName, isDestroy, isLast);
        }
    }

    private void HideWindow(WindowProxy window, bool isDestroy = true)
    {
        HideWindow(0, window, isDestroy);
    }

    private void HideWindow(int layer, WindowProxy window, bool isDestroy = true)
    {
        WindowManager winManager = null;
        if (winManagerMap.TryGetValue(layer, out winManager))
        {
            winManager.HideWindow(window, isDestroy);
        }
    }







//    public ITip ShowTip()
//    {
//		UIRoot tempRoot = uiRoot;
//		if (tempRoot == null)
//		{
//			return null;
//		}
//
//        if (tipPanel == null)
//        {
//			tipPanel = tempRoot.GetComponentInChildren<TipPanel>();
//        }
//
//        return tipPanel.ShowTip();
//    }
//
//    public ITip ShowTip(Tip prefab,float showtime)
//    {
//		UIRoot tempRoot = uiRoot;
//		if (tempRoot == null)
//		{
//			return null;
//		}
//
//        if (tipPanel == null)
//        {
//			tipPanel = tempRoot.GetComponentInChildren<TipPanel>();
//        }
//        return tipPanel.ShowTip(prefab, showtime);
//    }



//    TipPanel tipPanel;
//    public GameObject GetTipPanel()
//    {
//        UIRoot tempRoot = uiRoot;
//        if (tempRoot == null)
//        {
//            return null;
//        }
//
//        if (tipPanel == null)
//        {
//            tipPanel = tempRoot.GetComponentInChildren<TipPanel>();
//        }
//        return tipPanel.gameObject;
//    }

	RestrictControlRegionManager restrictControlRegionManager;
	public RestrictControlRegionManager GetRestrictControlRegionManager()
	{
		var tempRoot = uiRoot;
		if (tempRoot == null)
		{
			return null;
		}

		if (restrictControlRegionManager == null)
		{
			restrictControlRegionManager = tempRoot.GetComponentInChildren<RestrictControlRegionManager>();
		}
		return restrictControlRegionManager;
	}

    GameObject globalResObj = null;
    public void CreateGlobalResource(System.Action callback)
    {
        if (globalResObj != null)
        {
            if(callback != null)
            {
                callback();
            }
            return;
        }

        UIGlobalResource temp = uiRoot.GetComponent<UIGlobalResource>();
        ResourceManager.LoadAssetAsync(temp.UIRootPrefabPath, (prefabObj, path) =>
            {
                if(prefabObj == null)
                {
                    throw new System.Exception("prefab not found: " + temp.UIRootPrefabPath);
                }

                Object tempPrefab = prefabObj as Object;
                globalResObj = GameObject.Instantiate(tempPrefab, uiRoot.transform) as GameObject;
                if(callback != null)
                {
                    callback();
                }
            });
    }

    public void DestroyGlobalResource()
    {
        if (globalResObj == null)
        {
            return;
        }   

        GameObject.Destroy(globalResObj);
        globalResObj = null;

//        tipPanel = null;
        restrictControlRegionManager = null;
    }
}
